package cn.coder.toolkit;

import io.minio.BucketExistsArgs;
import io.minio.DownloadObjectArgs;
import io.minio.GetObjectArgs;
import io.minio.ListObjectsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.ObjectWriteResponse;
import io.minio.RemoveBucketArgs;
import io.minio.RemoveObjectArgs;
import io.minio.RemoveObjectsArgs;
import io.minio.Result;
import io.minio.UploadObjectArgs;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.ServerException;
import io.minio.errors.XmlParserException;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 官方文档
 * https://min.io/docs/minio/linux/developers/java/API.html
 */
public final class MinIOKit {

    private MinIOKit() {}

    public static MinioClient connect(String endpoint, String accessKey, String secretKey) {
        return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();
    }

    public static class Buckets {

        public static boolean exists(MinioClient client, String bucket) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            return client.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
        }

        public static boolean notExists(MinioClient client, String bucket) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            return !client.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
        }

        public static void make(MinioClient client, String bucket) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            client.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
        }

        public static void remove(MinioClient client, String bucket) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            client.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
        }

        public static List<Bucket> list(MinioClient client) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            return client.listBuckets();
        }

    }

    public static class Objects {

        /**
         * UploadObjectArgs.builder().bucket().object().filename().contentType().build()
         */
        public static ObjectWriteResponse upload(MinioClient client, UploadObjectArgs args) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            return client.uploadObject(args);
        }

        /**
         * @param bucket 桶名称
         * @param object 对象名称, 支持多层目录, 如 .object("sub/a.png") / .object("sub/sub/a.png")
         * @param file 本地文件
         */
        public static ObjectWriteResponse upload(MinioClient client, String bucket, String object, File file) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            return client.uploadObject(UploadObjectArgs.builder().bucket(bucket).object(object).filename(file.getPath()).build());
        }

        public static ObjectWriteResponse upload(MinioClient client, String bucket, File file) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            return upload(client, bucket, file.getName(), file);
        }

        /**
         * DownloadObjectArgs.builder().bucket().object().filename().build()
         */
        public static void download(MinioClient client, DownloadObjectArgs args) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            client.downloadObject(args);
        }

        public static void download(MinioClient client, String bucket, String object, File file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            client.downloadObject(DownloadObjectArgs.builder().bucket(bucket).object(object).filename(file.getPath()).build());
        }

        public static InputStream get(MinioClient client, String bucket, String object) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            return client.getObject(GetObjectArgs.builder().bucket(bucket).object(object).build());
        }

        public static void remove(MinioClient client, RemoveObjectArgs args) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            client.removeObject(args);
        }

        public static void remove(MinioClient client, String bucket, String object) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            client.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(object).build());
        }

        public static void remove(MinioClient client, RemoveObjectsArgs args) {
            client.removeObjects(args);
        }

        public static void remove(MinioClient client, String bucket, List<String> objects) {
            client.removeObjects(RemoveObjectsArgs.builder().bucket(bucket).objects(objects.stream().map(DeleteObject::new).collect(Collectors.toList())).build());
        }

        /**
         * startAfter() 和 max() 可以实现分页查询
         * prefix() 可以实现子文件夹查询, 注意一定要以 "/" 结尾, 如 .prefix("sub/") / .prefix("sub/sub/")
         */
        public static Iterable<Result<Item>> list(MinioClient client, ListObjectsArgs args) {
            return client.listObjects(args);
        }

        public static Iterable<Result<Item>> list(MinioClient client, String bucket) {
            return client.listObjects(ListObjectsArgs.builder().recursive(true).bucket(bucket).build());
        }

        public static Iterable<Result<Item>> list(MinioClient client, String bucket, String prefix) {
            return client.listObjects(ListObjectsArgs.builder().recursive(true).bucket(bucket).prefix(prefix).build());
        }

    }

    public static void main(String[] args) {

        try {

            String bucket = "test";
//            MinioClient client = connect("https://play.min.io", "Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG");
            MinioClient client = connect("http://192.168.88.129:9000", "M7NGKTa9DWNd7v9B48hv", "G38V0efmVyIOqVWdZmvaXYZVf6gxF1ehuc95kiiW");

            if (Buckets.notExists(client, bucket)) {
                Buckets.make(client, bucket);
            }

            Objects.upload(client, bucket, "test/a.jpg", new File("C:\\coder\\resource\\图片\\微信图片_20230813191147.jpg"));

            for (Result<Item> test : Objects.list(client, "test")) {
                System.out.println(test.get().objectName());
            }

        } catch (Throwable cause) {
            cause.printStackTrace();
        }

    }

}
